package device

import (
	"github.com/yuin/gluamapper"
	lua "github.com/yuin/gopher-lua"
	"goAdapter/setting"
)

// 设备模板
type DeviceInfoTemplate struct {
	LastCommRTC    string `json:"LastCommRTC"`    //最后一次通信时间戳
	CommTotalCnt   int    `json:"CommTotalCnt"`   //通信总次数
	CommSuccessCnt int    `json:"CommSuccessCnt"` //通信成功次数
	CurCommFailCnt int    `json:"-"`              //当前通信失败次数
	CommStatus     string `json:"CommStatus"`     //通信状态
	DevState       string `json:"-"`              //当前错误信息
}

//type SetNodeInfoTemplate struct {
//	DevId  string `json:"DevId"`
//	NodeId string `json:"NodeId"`
//	Val    string `json:"Val"`
//}

type NodeEventTemplate struct {
	Type   string //事件类型，set
	DevId  string `json:"DevId"`
	NodeId string `json:"NodeId"`
	Val    string `json:"Val"`
}

/*
func (d *DeviceInfoTemplate) NewVariables() []DeviceTSLPropertyTemplate {

	properties := make([]DeviceTSLPropertyTemplate, 0)

	for _, v := range DeviceTSLMap {
		if v.Name == d.Type {
			properties = append(properties, v.Properties...)
		}
	}

	return properties
}

func (d *DeviceInfoTemplate) NewServices() []DeviceTSLServiceTempalte {

	services := make([]DeviceTSLServiceTempalte, 0)

	for _, v := range DeviceTSLMap {
		if v.Name == d.Type {
			services = append(services, v.Services...)
		}
	}

	return services
}
*/

func (d *DeviceInfoTemplate) GenerateGetRealVariables(lState *lua.LState, sAddr string, step int) ([]byte, bool, bool) {

	type LuaVariableMapTemplate struct {
		Status   string `json:"Status"`
		Variable []*byte
	}
	if lState != nil {
		//调用GenerateGetRealVariables
		err := lState.CallByParam(lua.P{
			Fn:      lState.GetGlobal("GenerateGetRealVariables"),
			NRet:    1,
			Protect: true,
		}, lua.LString(sAddr), lua.LNumber(step))
		if err != nil {
			setting.ZAPS.Warnf("GenerateGetRealVariables 调用函数错误 %v", err)
			return nil, false, false
		}

		//获取返回结果
		ret := lState.Get(-1)
		_, ok := ret.(*lua.LTable)
		if ok == false {
			setting.ZAPS.Warnf("GenerateGetRealVariables 返回结果错误 %v", err)
			return nil, false, false
		}
		lState.Pop(1)

		LuaVariableMap := LuaVariableMapTemplate{}
		if err := gluamapper.Map(ret.(*lua.LTable), &LuaVariableMap); err != nil {
			setting.ZAPS.Warnf("GenerateGetRealVariables 返回结果格式化错误 %v", err)
			return nil, false, false
		}

		result := false
		continuous := false //后续是否有报文
		nBytes := make([]byte, 0)
		if len(LuaVariableMap.Variable) > 0 {
			result = true
			for _, v := range LuaVariableMap.Variable {
				nBytes = append(nBytes, *v)
			}
			if LuaVariableMap.Status == "0" {
				continuous = false
			} else {
				continuous = true
			}
		} else {
			//setting.ZAPS.Debug("GenerateGetRealVariables 返回结果长度为0")
			result = true
		}
		return nBytes, result, continuous
	}
	return nil, false, false
}

func (d *DeviceInfoTemplate) DeviceCustomCmd(lState *lua.LState, sAddr string, cmdName string, cmdParam string, step int) ([]byte, bool, bool) {

	type LuaVariableMapTemplate struct {
		Status   string  `json:"Status"`
		Variable []*byte `json:"Variable"`
	}

	//log.Printf("cmdParam %+v\n", cmdParam)
	if lState != nil {
		var err error
		var ret lua.LValue

		//调用DeviceCustomCmd
		err = lState.CallByParam(lua.P{
			Fn:      lState.GetGlobal("DeviceCustomCmd"),
			NRet:    1,
			Protect: true,
		}, lua.LString(sAddr),
			lua.LString(cmdName),
			lua.LString(cmdParam),
			lua.LNumber(step))
		if err != nil {
			setting.ZAPS.Warnf("DeviceCustomCmd err %v", err)
			return nil, false, false
		}

		//获取返回结果
		ret = lState.Get(-1)
		_, ok := ret.(*lua.LTable)
		if ok == false {
			setting.ZAPS.Warnf("DeviceCustomCmd 返回结果错误 %v", err)
			return nil, false, false
		}
		lState.Pop(1)

		LuaVariableMap := LuaVariableMapTemplate{}
		if err := gluamapper.Map(ret.(*lua.LTable), &LuaVariableMap); err != nil {
			setting.ZAPS.Warnf("DeviceCustomCmd gluamapper.Map err %v", err)
			return nil, false, false
		}

		result := false
		continuous := false //后续是否有报文
		if LuaVariableMap.Status == "0" {
			continuous = false
		} else {
			continuous = true
		}
		nBytes := make([]byte, 0)
		if len(LuaVariableMap.Variable) > 0 {
			result = true
			for _, v := range LuaVariableMap.Variable {
				nBytes = append(nBytes, *v)
			}
		} else {
			result = false
		}
		return nBytes, result, continuous
	}
	return nil, false, false
}

func (d *DeviceInfoTemplate) AnalysisRx(lState *lua.LState, sAddr string, variables []DeviceTSLPropertyTemplate, rxBuf []byte, rxBufCnt int) chan bool {

	status := make(chan bool, 1)
	//
	//type LuaVariableTemplate struct {
	//	Index   int
	//	Name    string
	//	Label   string
	//	Type    string
	//	Value   interface{}
	//	Explain string
	//}
	//
	//type LuaVariableMapTemplate struct {
	//	Status   string `json:"Status"`
	//	Variable []*LuaVariableTemplate
	//}
	//if lState != nil {
	//	tbl := lua.LTable{}
	//	for _, v := range rxBuf {
	//		tbl.Append(lua.LNumber(v))
	//	}
	//	lState.SetGlobal("rxBuf", luar.New(lState, &tbl))
	//
	//	//AnalysisRx
	//	err := lState.CallByParam(lua.P{
	//		Fn:      lState.GetGlobal("AnalysisRx"),
	//		NRet:    1,
	//		Protect: true,
	//	}, lua.LString(sAddr), lua.LNumber(rxBufCnt))
	//	if err != nil {
	//		setting.ZAPS.Warnf("AnalysisRx 执行接收解析错误 %v", err)
	//		return status
	//	}
	//
	//	//获取返回结果
	//	ret := lState.Get(-1)
	//	_, ok := ret.(*lua.LTable)
	//	if ok == false {
	//		setting.ZAPS.Warnf("AnalysisRx 返回结果错误 %v", err)
	//		return status
	//	}
	//	lState.Pop(1)
	//
	//	LuaVariableMap := LuaVariableMapTemplate{}
	//
	//	if err := gluamapper.Map(ret.(*lua.LTable), &LuaVariableMap); err != nil {
	//		setting.ZAPS.Warnf("AnalysisRx gluamapper.Map err %v", err)
	//		return status
	//	}
	//
	//	timeNowStr := time.Now().Format("2006-01-02 15:04:05")
	//	value := DeviceTSLPropertyValueTemplate{}
	//	if LuaVariableMap.Status == "0" {
	//		if len(LuaVariableMap.Variable) > 0 {
	//			for _, lv := range LuaVariableMap.Variable {
	//				for k, p := range variables {
	//					if lv.Name == p.Name {
	//						value.Index = lv.Index
	//						switch p.Type {
	//						case PropertyTypeInt32:
	//							value.Value = (int32)(lv.Value.(float64))
	//						case PropertyTypeUInt32:
	//							value.Value = (uint32)(lv.Value.(float64))
	//						case PropertyTypeDouble:
	//							decimals, _ := strconv.Atoi(p.Params.Decimals)
	//							value.Value = lv.Value.(float64) / math.Pow10(decimals)
	//						case PropertyTypeString:
	//							value.Value = lv.Value.(string)
	//						}
	//
	//						value.Explain = lv.Explain
	//						value.TimeStamp = timeNowStr
	//
	//						if len(variables[k].Value) < 100 {
	//							variables[k].Value = append(variables[k].Value, value)
	//						} else {
	//							variables[k].Value = variables[k].Value[1:]
	//							variables[k].Value = append(variables[k].Value, value)
	//						}
	//					}
	//				}
	//			}
	//		}
	//		status <- true
	//	}
	//}
	return status
}
